/*
 *  Copyright © OpenAtom Foundation.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.openatom.ubml.model.common.definition.cef.entity;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.ArrayList;
import java.util.List;
import org.openatom.ubml.model.common.definition.cef.IGspCommonDataType;
import org.openatom.ubml.model.common.definition.cef.IGspCommonField;
import org.openatom.ubml.model.common.definition.cef.collection.GspAssociationCollection;
import org.openatom.ubml.model.common.definition.cef.collection.GspEnumValueCollection;
import org.openatom.ubml.model.common.definition.cef.collection.GspFieldCollection;
import org.openatom.ubml.model.common.definition.cef.element.ElementDefaultVauleType;
import org.openatom.ubml.model.common.definition.cef.element.EnumIndexType;
import org.openatom.ubml.model.common.definition.cef.element.FieldCollectionType;
import org.openatom.ubml.model.common.definition.cef.element.GspAssociation;
import org.openatom.ubml.model.common.definition.cef.element.GspElementDataType;
import org.openatom.ubml.model.common.definition.cef.element.GspElementObjectType;
import org.openatom.ubml.model.common.definition.cef.json.CefNames;
import org.openatom.ubml.model.common.definition.cef.util.Guid;

/**
 * The Definition Of DimensionInfo
 *
 * @ClassName: DimensionInfo
 * @Author: Benjamin Gong
 * @Date: 2021/1/11 17:13
 * @Version: V1.0
 */
public class GspCommonField implements IGspCommonField {
    // region 私有属性
    @JsonProperty(CefNames.ID)
    private String id = Guid.newGuid().toString();
    @JsonProperty(CefNames.CODE)
    private String code = "";
    @JsonProperty(CefNames.NAME)
    private String name = "";
    @JsonProperty(CefNames.LABEL_ID)
    private String labelId = "";
    @JsonProperty(CefNames.DATA_TYPE)
    private GspElementDataType dataType = GspElementDataType.String;
    @JsonProperty(CefNames.DEFAULT_VALUE)
    private String defaultValue = "";
    @JsonProperty(CefNames.DEFAULT_VALUE_TYPE)
    private ElementDefaultVauleType defaultValueType = ElementDefaultVauleType.Vaule;
    @JsonProperty(CefNames.LENGTH)
    private int length;
    @JsonProperty(CefNames.PRECISION)
    private int precision;
    @JsonProperty(CefNames.IS_VIRTUAL)
    private boolean isVirtual;
    @JsonProperty(CefNames.IS_REQUIRE)
    private boolean isRequire = true;
    @JsonProperty(CefNames.IS_MULTI_LANGUAGE)
    private boolean isMultilLanguage;
    @JsonProperty(CefNames.IS_VIRTUAL)
    private transient IGspCommonDataType belongObject;
    @JsonProperty(CefNames.CHILD_ELEMENTS)
    //todo:j-json
    private transient GspFieldCollection childElements;
    @JsonProperty(CefNames.MAPPING_RELATION)
    //todo:j-json
    private transient MappingRelation mappingRelation;
    //todo:j-json
    @JsonIgnore
    private transient GspAssociationCollection childAssociations = new GspAssociationCollection();
    //todo:j-json
    private transient GspEnumValueCollection enumValueCollection;
    @JsonProperty(CefNames.IS_REF_ELEMENT)
    private boolean isRefElement;
    @JsonProperty(CefNames.REF_ELEMENT_ID)
    private String refelementId = "";
    private transient GspAssociation parentAssociation;
    @JsonProperty(CefNames.OBJECT_TYPE)
    private GspElementObjectType objectType = GspElementObjectType.None;
    private CustomizationInfo customizationInfo = new CustomizationInfo();
    @JsonProperty(CefNames.ENUM_INDEX_TYPE)
    private EnumIndexType enumIndexType = EnumIndexType.Integer;
    @JsonProperty(CefNames.BE_LABEL)
    private List<String> beLabel;

    @JsonProperty(CefNames.BIZ_TAG_IDS)
    private List<String> bizTagIds;


    @JsonProperty(CefNames.ENABLE_RTRIM)
    private boolean enableRtrim = true;

    @JsonProperty(CefNames.IS_BIG_NUMBER)
    private boolean bigNumber = false;
    private boolean privateIsRef;

    // region 公共属性
    /**
     * 是否启用业务字段
     */
    private boolean privateIsUdt;
    /**
     * 业务字段包名
     */
    private String privateUdtPkgName;
    /**
     * 业务字段ID
     */
    private String privateUdtID;
    /**
     * 业务字段ID
     */
    private String privateUdtName;
    private FieldCollectionType privateCollectionType = FieldCollectionType.forValue(0);
    /**
     * 是否udt关联带出字段
     */
    private boolean privateIsFromAssoUdt;
    /**
     * 国际化项前缀
     */
    private String privateI18nResourceInfoPrefix;
    /**
     * 动态属性设置
     */
    private DynamicPropSetInfo privateDynamicPropSetInfo = new DynamicPropSetInfo();

    // endregion
    public GspCommonField() {
        setIsRef(false);
        setCollectionType(FieldCollectionType.None);
        setEnumIndexType(EnumIndexType.Integer);
    }

    public String getID() {
        return id;
    }

    public void setID(String value) {
        id = value;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String value) {
        code = value;
    }

    public String getName() {
        return name;
    }

    public void setName(String value) {
        name = value;
    }

    public String getLabelID() {
        return labelId;
    }

    public void setLabelID(String value) {
        labelId = value;
    }

    public List<String> getBeLabel() {
        if (beLabel == null) {
            beLabel = new ArrayList<String>();
            return beLabel;
        }
        return beLabel;
    }

    public void setBeLabel(List<String> value) {
        beLabel = value;
    }

    public List<String> getBizTagIds() {
        if (this.bizTagIds == null) {
            bizTagIds = new ArrayList<String>();
            return bizTagIds;
        }
        return bizTagIds;
    }

    public void setBizTagIds(List<String> value) {
        bizTagIds = value;
    }

    public GspElementDataType getMDataType() {
        return dataType;
    }

    public void setMDataType(GspElementDataType value) {
        dataType = value;
    }

    public String getDefaultValue() {
        return defaultValue;
    }

    public void setDefaultValue(String value) {
        defaultValue = value;
    }

    @Override
    public final ElementDefaultVauleType getDefaultValueType() {
        return defaultValueType;
    }

    @Override
    public final void setDefaultValueType(ElementDefaultVauleType value) {
        defaultValueType = value;
    }

    @Override
    public GspElementObjectType getObjectType() {
        return objectType;
    }

    public void setObjectType(GspElementObjectType value) {
        objectType = value;
    }

    public int getLength() {
        return length;
    }

    public void setLength(int value) {
        length = value;
    }

    public int getPrecision() {
        return precision;
    }

    public void setPrecision(int value) {
        precision = value;
    }

    public boolean getIsVirtual() {
        return isVirtual;
    }

    public void setIsVirtual(boolean value) {
        isVirtual = value;
    }

    public boolean getIsRequire() {
        return isRequire;
    }

    public void setIsRequire(boolean value) {
        isRequire = value;
    }

    public boolean getIsMultiLanguage() {
        return isMultilLanguage;
    }

    public void setIsMultiLanguage(boolean value) {
        isMultilLanguage = value;
    }

    public boolean getIsRef() {
        return privateIsRef;
    }

    public void setIsRef(boolean value) {
        privateIsRef = value;
    }

    /**
     * bigNumber
     */
    public boolean isBigNumber() {
        return this.bigNumber;
    }

    public void setIsBigNumber(boolean value) {
        this.bigNumber = value;
    }

    public IGspCommonDataType getBelongObject() {
        if (this.getIsRefElement() && belongObject == null) {
            return this.getParentAssociation().getBelongElement().getBelongObject();
        }
        return belongObject;
    }

    public void setBelongObject(IGspCommonDataType value) {
        belongObject = value;
    }

    public GspFieldCollection getChildElements() {
        if (childElements == null) {
            childElements = new GspFieldCollection();
        }
        return childElements;
    }

    public void setChildElements(GspFieldCollection value) {
        childElements = value;
    }

    public MappingRelation getMappingRelation() {
        if (mappingRelation == null) {
            mappingRelation = new MappingRelation();
        }
        return mappingRelation;
    }

    public void setMappingRelation(MappingRelation mappingInfos) {
        mappingRelation = mappingInfos;
    }

    /**
     * /////关联引用
     */
    public GspAssociationCollection getChildAssociations() {
        return childAssociations;
    }

    public void setChildAssociations(GspAssociationCollection value) {
        childAssociations = value;
    }

    public final boolean getHasAssociation() {
        if (getChildAssociations() == null || getChildAssociations().size() == 0) {
            return false;
        }
        return true;
    }

    public GspEnumValueCollection getContainEnumValues() {
        return enumValueCollection;
    }

    public void setContainEnumValues(GspEnumValueCollection value) {
        enumValueCollection = value;
    }

    public boolean getIsRefElement() {
        return isRefElement;
    }

    public void setIsRefElement(boolean value) {
        isRefElement = value;
    }

    public String getRefElementId() {
        return refelementId;
    }

    public void setRefElementId(String value) {
        refelementId = value;
    }

    public GspAssociation getParentAssociation() {
        return parentAssociation;
    }

    public void setParentAssociation(GspAssociation value) {
        parentAssociation = value;
    }

    public boolean getIsUdt() {
        return privateIsUdt;
    }

    public void setIsUdt(boolean value) {
        privateIsUdt = value;
    }

    public String getUdtPkgName() {
        return privateUdtPkgName;
    }

    public void setUdtPkgName(String value) {
        privateUdtPkgName = value;
    }

    public String getUdtID() {
        return privateUdtID;
    }

    public void setUdtID(String value) {
        privateUdtID = value;
    }

    public final String getUdtName() {
        return privateUdtName;
    }

    public final void setUdtName(String value) {
        privateUdtName = value;
    }

    public FieldCollectionType getCollectionType() {
        return privateCollectionType;
    }

    public final void setCollectionType(FieldCollectionType value) {
        privateCollectionType = value;
    }

    public final boolean getIsFromAssoUdt() {
        return privateIsFromAssoUdt;
    }

    public final void setIsFromAssoUdt(boolean value) {
        privateIsFromAssoUdt = value;
    }

    public final String getI18nResourceInfoPrefix() {
        return privateI18nResourceInfoPrefix;
    }

    public final void setI18nResourceInfoPrefix(String value) {
        privateI18nResourceInfoPrefix = value;
    }

    public final DynamicPropSetInfo getDynamicPropSetInfo() {
        return privateDynamicPropSetInfo;
    }

    public final void setDynamicPropSetInfo(DynamicPropSetInfo value) {
        privateDynamicPropSetInfo = value;
    }


    public CustomizationInfo getCustomizationInfo() {
        return customizationInfo;
    }

    public void setCustomizationInfo(CustomizationInfo customizationInfo) {
        this.customizationInfo = customizationInfo;
    }

    /**
     * 索引类型
     */
    public final EnumIndexType getEnumIndexType() {
        return enumIndexType;
    }

    public final void setEnumIndexType(EnumIndexType value) {
        enumIndexType = value;
    }
    // endregion

    // region 方法
    public final boolean hasNoneRefElementInAssociation() {
        if (getHasAssociation() == false) {
            return false;
        }

        return false;
    }

    /**
     * 若当前字段引用联动关联udt,返回是否包含非udt带出字段
     *
     * @return
     */
    public final boolean containRefElementNotFromAssoUdt() {
        if (!getIsUdt() || getObjectType() != GspElementObjectType.Association) {
            throw new RuntimeException("#GspBefError#" + "字段" + getCode()
                    + "不是引用关联udt的字段，不可调用方法ContainRefElementNotFromAssoUdt()。" + "#GspBefError#");
        }
        if (getChildAssociations() == null || getChildAssociations().size() == 0) {
            throw new RuntimeException("#GspBefError#" + "字段" + getCode() + "为关联字段，无关联信息。" + "#GspBefError#");
        }
        for (GspAssociation asso : getChildAssociations()) {
            if (asso.getRefElementCollection() == null || asso.getRefElementCollection().size() == 0) {
                throw new RuntimeException("#GspBefError#" + "字段" + getCode() + "的关联中，关联字段为空。" + "#GspBefError#");
            }
            for (IGspCommonField field : asso.getRefElementCollection()) {
                if (!field.getIsFromAssoUdt()) {
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public IGspCommonField clone(IGspCommonDataType absObj, GspAssociation association) {
        GspCommonField newObj = null;
        try {
            newObj = (GspCommonField)super.clone();
        } catch (CloneNotSupportedException e) {
            return null;
        }
        if (newObj == null) {
            return null;
        }
        newObj.belongObject = absObj;
        newObj.parentAssociation = association;
        if (childAssociations != null) {
            newObj.childAssociations = new GspAssociationCollection();
            for (GspAssociation item : childAssociations) {
                newObj.childAssociations.add(item.clone(newObj));
            }
        }
        if (enumValueCollection != null) {
            newObj.enumValueCollection = enumValueCollection.clone();
        }
        return newObj;
    }

    public boolean isEnableRtrim() {
        return enableRtrim;
    }

    public void setEnableRtrim(boolean value) {
        this.enableRtrim = value;
    }
}
